package com.hq.ims.data.service;

import com.google.common.collect.Lists;
import com.hq.ims.data.dao.CompanyDepartmentEmployeeMapper;
import com.hq.ims.data.entity.*;
import com.hq.ims.data.utils.ErrMsgConstant;
import com.hq.ims.data.vo.CompanyDepartmentEmployeeMapstruct;
import com.hq.ims.data.vo.CompanyDepartmentMapstruct;
import com.hq.ims.data.vo.PermissionRoleMapstruct;
import com.hq.ims.data.vo.UserMapstruct;
import com.hq.mybatis.base.BaseService;
import com.hq.mybatis.base.page.RequestPage;
import com.hq.utils.util.BooleanUtils;
import com.hq.utils.util.ListUtils;
import com.hq.utils.util.ObjectUtils;
import com.hq.utils.util.StringUtils;
import com.hq.web.utils.SpringBootValidateUtils;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * jiang bai ping
 *
 * @Email 526666031@qq.com
 * @Detail 部门用户关联表服务实现类
 */
@Service
@Slf4j
@Transactional(rollbackFor = Exception.class)
public class BaseCompanyDepartmentEmployeeService extends BaseService<CompanyDepartmentEmployeeMapper, CompanyDepartmentEmployee> {

    @Resource
    private BaseUserService baseUserService;
    @Resource
    private BaseCompanyDepartmentService baseCompanyDepartmentService;
    @Resource
    private BaseCompanyService baseCompanyService;
    @Resource
    private BaseCompanyEmployeeService baseCompanyEmployeeService;
    @Resource
    private BasePermissionMapAuthorityDepartmentService basePermissionMapGroupDepartmentService;
    @Resource
    private BasePermissionMapAuthorityUserService basePermissionMapGroupUserService;
    @Resource
    private BasePermissionAuthorityService basePermissionAuthorityService;
    @Resource
    private BasePermissionMapAuthorityRoleService basePermissionMapGroupRoleService;
    @Resource
    private BaseCompanyDepartmentEmployeeService baseCompanyMapDepartmentUserService;
    @Resource
    private BasePermissionMapRoleUserService basePermissionMapRoleUserService;
    @Resource
    private BasePermissionRoleService basePermissionRoleService;


    /**
     * 根据部门id获取用户
     *
     * @param companyDepartmentId 部门ID
     */
    public List<UserMapstruct.UserAndCompanySimpleVo> getUserByDepartmentId(@NonNull String companyDepartmentId) {
        //获取部门和用户的关系
        List<CompanyDepartmentEmployee> companyMapDepartmentUserList = this.lambdaQuery()
                .eq(CompanyDepartmentEmployee::getCompanyDepartmentId, companyDepartmentId)
                .list();
        List<UserMapstruct.UserAndCompanySimpleVo> userVoList = assembleUserAndCompanySimpleVoList(companyMapDepartmentUserList);
        return userVoList;
    }

    /**
     * 添加部门用户
     */
    @Transactional(rollbackFor = Exception.class)
    public Boolean addData(
            @NonNull String companyId,
            @NonNull String departmentId,
            @NonNull String userId,
            String jobName,
            @NonNull Boolean isPartTimeJob
    ) {
        //部门是否存在
        CompanyDepartment companyDepartment = baseCompanyDepartmentService.getById(departmentId);
        ObjectUtils.isNullThrow(companyDepartment, ErrMsgConstant.DEPARTMENT_INFO_NOT_EXISTS);
        //获取公司实体
        Company company = baseCompanyService.getById(companyId);
        ObjectUtils.isNullThrow(company, ErrMsgConstant.COMPANY_INFO_NOT_EXISTS);

        //判断用户是否已加入公司
        if (!this.isExistsUserDepartment(userId, departmentId, isPartTimeJob)) {
            //查询公司员工ID
            List<CompanyEmployee> companyEmployeeList = baseCompanyEmployeeService.getByUserIdAndCompanyId(userId, companyId, isPartTimeJob);
            CompanyEmployee companyEmployee = companyEmployeeList.get(0);
            //添加公司部门成员companyEmployee
            CompanyDepartmentEmployee companyMapDepartmentUser = new CompanyDepartmentEmployee();
            companyMapDepartmentUser.setCompanyId(companyId);
            companyMapDepartmentUser.setUserId(userId);
            companyMapDepartmentUser.setCompanyDepartmentId(departmentId);
            companyMapDepartmentUser.setJobName(jobName);
            companyMapDepartmentUser.setIsPrincipal(false);
            companyMapDepartmentUser.setIsPartTimeJob(false);
            companyMapDepartmentUser.setCompanyEmployeeId(companyEmployee.getCompanyEmployeeId());
            companyMapDepartmentUser.insert();
        }
        return true;
    }

    /**
     * 用户是否已经加入在该部门
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean isExistsUserDepartment(
            @NonNull String companyDepartmentId,
            @NonNull String userId,
            Boolean isPartTimeJob
    ) {
        Long count = this.lambdaQuery()
                .eq(CompanyDepartmentEmployee::getUserId, userId)
                .eq(CompanyDepartmentEmployee::getCompanyDepartmentId, companyDepartmentId)
                .eq(isPartTimeJob != null, CompanyDepartmentEmployee::getIsPartTimeJob, isPartTimeJob)
                .count();
        return count > 0;
    }

    /**
     * 设置用户是否为部门负责人
     */
    @Transactional(rollbackFor = Exception.class)
    public void setDepartmentUserIsPrincipal(
            CompanyDepartmentMapstruct.SetDepartmentPrincipal saveVo
    ) {
        SpringBootValidateUtils.validate(saveVo);

        //取消该部门所有用户的负责人身份
        boolean bl = this.lambdaUpdate()
                .eq(CompanyDepartmentEmployee::getCompanyDepartmentId, saveVo.getCompanyDepartmentId())
                .set(CompanyDepartmentEmployee::getIsPrincipal, false)
                .update();
        BooleanUtils.isFalseThrow(bl, ErrMsgConstant.OPERATION_FAILURE);

        boolean isExistsUserDepartment = this.isExistsUserDepartment(saveVo.getCompanyDepartmentId(), saveVo.getUserId(), null);
        ObjectUtils.isNullThrow(isExistsUserDepartment, String.format("用户不在该部门中,请联系管理员,用户id:%s", saveVo.getUserId()));

        //根据每个用户id+部门id完成部门负责人的修改
        bl = this.lambdaUpdate()
                .eq(CompanyDepartmentEmployee::getUserId, saveVo.getUserId())
                .eq(CompanyDepartmentEmployee::getCompanyDepartmentId, saveVo.getCompanyDepartmentId())
                .set(CompanyDepartmentEmployee::getIsPrincipal, saveVo.getIsPrincipal())
                .update();

        BooleanUtils.isFalseThrow(bl, ErrMsgConstant.OPERATION_FAILURE);
    }


    /**
     * 根据用户id和部门id获取用户所有所在部门
     */
    public List<CompanyDepartmentEmployee> getByUserIdAndDepartmentId(
            @NonNull String userId,
            @NonNull String companyDepartmentId,
            Boolean isPartTimeJob
    ) {
        List<CompanyDepartmentEmployee> companyDepartmentEmployeeList = this.lambdaQuery()
                .eq(CompanyDepartmentEmployee::getUserId, userId)
                .eq(CompanyDepartmentEmployee::getCompanyDepartmentId, companyDepartmentId)
                .eq(isPartTimeJob != null, CompanyDepartmentEmployee::getIsPartTimeJob, isPartTimeJob)
                .list();
        return companyDepartmentEmployeeList;
    }

    /**
     * 根据用户id和部门id获取用户所有所在部门
     */
    public List<CompanyDepartmentEmployee> getByUserIdAndDepartmentId(
            @NonNull String userId,
            @NonNull String companyDepartmentId
    ) {
        List<CompanyDepartmentEmployee> companyDepartmentEmployeeList = this.lambdaQuery()
                .eq(CompanyDepartmentEmployee::getUserId, userId)
                .eq(CompanyDepartmentEmployee::getCompanyDepartmentId, companyDepartmentId)
                .list();
        return companyDepartmentEmployeeList;
    }

    /**
     * 根据用户id和公司id获取用户所有所在部门
     */
    public List<CompanyDepartmentEmployee> getByUserIdAndCompanyId(
            @NonNull String userId,
            @NonNull String companyId,
            Boolean isPartTimeJob
    ) {
        List<CompanyDepartmentEmployee> companyDepartmentEmployeeList = this.lambdaQuery()
                .eq(CompanyDepartmentEmployee::getUserId, userId)
                .eq(CompanyDepartmentEmployee::getCompanyId, companyId)
                .eq(isPartTimeJob != null, CompanyDepartmentEmployee::getIsPartTimeJob, isPartTimeJob)
                .list();
        return companyDepartmentEmployeeList;
    }

    /**
     * 根据用户id和部门id获取用户所有所在部门
     */
    public List<CompanyDepartmentEmployee> getListByUserIdAndDepartmentId(
            @NonNull String userId,
            Boolean isPartTimeJob
    ) {
        List<CompanyDepartmentEmployee> companyDepartmentEmployeeList = this.lambdaQuery()
                .eq(CompanyDepartmentEmployee::getUserId, userId)
                .eq(isPartTimeJob != null, CompanyDepartmentEmployee::getIsPartTimeJob, isPartTimeJob)
                .list();
        return companyDepartmentEmployeeList;
    }

    /**
     * 用户是否是部门得负责人
     *
     * @param userId       用户ID
     * @param departmentId 部门ID
     */
    public Boolean userIsPrincipal(
            @NonNull String userId,
            @NonNull String departmentId
    ) {
        return this.lambdaQuery()
                .eq(CompanyDepartmentEmployee::getUserId, userId)
                .eq(CompanyDepartmentEmployee::getCompanyDepartmentId, departmentId)
                .eq(CompanyDepartmentEmployee::getIsPrincipal, true)
                .count() > 0;
    }


    /**
     * 移动用户到相关部门
     *
     * @param moveUserVoList 移动用户账号
     * @param toDepartmentId 到哪个部门
     * @param jobName        工作名称
     * @return {@code Boolean }
     */
    public void moveUserToOtherDepartment(
            @NonNull List<CompanyDepartmentEmployeeMapstruct.MoveUserDetailVo> moveUserVoList,
            @NonNull String toDepartmentId,
            @NonNull String jobName
    ) {

        //校验要移动的部门是否存在
        CompanyDepartment toCompanyDepartment = baseCompanyDepartmentService.getById(toDepartmentId);
        ObjectUtils.isNullThrow(toCompanyDepartment, ErrMsgConstant.DEPARTMENT_INFO_NOT_EXISTS);

        for (CompanyDepartmentEmployeeMapstruct.MoveUserDetailVo moveUserVo : moveUserVoList) {
            //若部门无变化则跳过
            if (StringUtils.isNotEmpty(moveUserVo.getCompanyDepartmentId()) && moveUserVo.getCompanyDepartmentId().equals(toDepartmentId)) {
                return;
            }

            //获取源部门信息
            CompanyDepartment curCompanyDepartment = baseCompanyDepartmentService.getById(moveUserVo.getCompanyDepartmentId());
            //是否更换了公司
            boolean isChangeCompany = !curCompanyDepartment.getCompanyId().equals(toCompanyDepartment.getCompanyId());
            if (isChangeCompany) {
//               //更换了公司,删除原公司信息
                baseCompanyEmployeeService.delByUserIdAndCompanyIdAndDelOtherBus(moveUserVo.getUserId(), curCompanyDepartment.getCompanyId());
            }
            //用户重新加入公司
            this.joinCompany(
                    toCompanyDepartment.getCompanyId(),
                    moveUserVo.getUserId(),
                    toCompanyDepartment.getCompanyDepartmentId(),
                    jobName,
                    false
            );
        }
    }

    /**
     * 根据部门ID和公司ID获取
     *
     * @param departmentId 部门ID
     */
    public List<CompanyDepartmentEmployee> getByDepartmentIdAndCompanyId(
            @NonNull String departmentId,
            @NonNull String companyId,
            Boolean isPartTimeJob
    ) {
        List<CompanyDepartmentEmployee> companyDepartmentList = this.lambdaQuery()
                .eq(CompanyDepartmentEmployee::getCompanyDepartmentId, departmentId)
                .eq(isPartTimeJob != null, CompanyDepartmentEmployee::getIsPartTimeJob, isPartTimeJob)
                .eq(CompanyDepartmentEmployee::getCompanyId, companyId)
                .list();

        if (ListUtils.isNotExistsEle(companyDepartmentList)) {
            return ListUtils.newEmptyList();
        }

        return companyDepartmentList;
    }

    /**
     * 根据部门ID获取
     *
     * @param departmentId 部门ID
     */
    public List<CompanyDepartmentEmployee> getByDepartmentId(
            @NonNull String departmentId,
            Boolean isPartTimeJob
    ) {
        List<CompanyDepartmentEmployee> companyDepartmentList = this.lambdaQuery()
                .eq(CompanyDepartmentEmployee::getCompanyDepartmentId, departmentId)
                .eq(isPartTimeJob != null, CompanyDepartmentEmployee::getIsPartTimeJob, isPartTimeJob)
                .list();

        if (ListUtils.isNotExistsEle(companyDepartmentList)) {
            return null;
        }

        return companyDepartmentList;
    }

    /**
     * 根据部门ID获取
     *
     * @param departmentId 部门ID
     */
    public List<CompanyDepartmentEmployee> getDepartmentPrincipalByDepartmentId(
            @NonNull String departmentId
    ) {
        List<CompanyDepartmentEmployee> companyDepartmentList = this.lambdaQuery()
                .eq(CompanyDepartmentEmployee::getCompanyDepartmentId, departmentId)
                .eq(CompanyDepartmentEmployee::getIsPrincipal, true)
                .list();

        if (ListUtils.isNotExistsEle(companyDepartmentList)) {
            return null;
        }

        return companyDepartmentList;
    }

    /**
     * 用户加入部门
     *
     * @param companyId    公司ID
     * @param userId       用户ID
     * @param departmentId 部门ID
     * @param jobName      工作名称
     */
    @Transactional(rollbackFor = Exception.class)
    public void joinCompany(
            @NotNull String companyId,
            @NotNull String userId,
            @NotNull String departmentId,
            @NotNull String jobName,
            @NonNull Boolean isPartTimeJob
    ) {
        //1.只存入公司
        baseCompanyEmployeeService.addData(companyId, userId, isPartTimeJob);
        //2.正常添加公司部门
        if (StringUtils.isEmpty(departmentId)) {
            return;
        }
        Boolean departmentAddUserRes = this.addData(companyId, departmentId, userId, jobName, isPartTimeJob);
        BooleanUtils.isFalseThrow(departmentAddUserRes, "添加部门员工失败,请联系管理员");
    }

    public List<CompanyDepartmentEmployee> getByCompanyId(
            @NonNull String companyId,
            Boolean isPartTimeJob
    ) {
        if (StringUtils.isEmpty(companyId)) {
            return Lists.newArrayList();
        }

        List<CompanyDepartmentEmployee> companyDepartmentList = this.lambdaQuery()
                .eq(CompanyDepartmentEmployee::getCompanyId, companyId)
                .eq(isPartTimeJob != null, CompanyDepartmentEmployee::getIsPartTimeJob, isPartTimeJob)
                .list();

        if (ListUtils.isNotExistsEle(companyDepartmentList)) {
            return Lists.newArrayList();
        }

        return companyDepartmentList;
    }

    /**
     * 获取部门员工数量
     *
     * @param companyDepartmentId 部门ID
     */
    public long getEmployeeCountByDepartmentId(
            @NonNull String companyDepartmentId
    ) {
        Long count = this.lambdaQuery().eq(CompanyDepartmentEmployee::getCompanyDepartmentId, companyDepartmentId).count();
        return count;
    }

    public List<UserMapstruct.UserAndCompanySimpleVo> getDepartmentAllUserPage(
            RequestPage page,
            CompanyDepartmentEmployeeMapstruct.PageSearchVo searchVo
    ) {
        List<CompanyDepartmentEmployee> companyDepartmentEmployeeList = this.getBaseMapper().getDepartmentAllUserPage(page, searchVo);
        List<UserMapstruct.UserAndCompanySimpleVo> userAndCompanySimpleVoList = this.assembleUserAndCompanySimpleVoList(companyDepartmentEmployeeList);
        page.setRecords(userAndCompanySimpleVoList);
        return userAndCompanySimpleVoList;
    }


    /**
     * 组装UserAndCompanySimpleVo
     *
     * @param companyDepartmentEmployeeList 员工数据
     */
    private List<UserMapstruct.UserAndCompanySimpleVo> assembleUserAndCompanySimpleVoList(
            List<CompanyDepartmentEmployee> companyDepartmentEmployeeList
    ) {

        List<UserMapstruct.UserAndCompanySimpleVo> userVoList = new ArrayList<>(0);
        if (ListUtils.isNotExistsEle(companyDepartmentEmployeeList)) {
            return userVoList;
        }

        //用户ID去重
        List<String> userIdList = companyDepartmentEmployeeList.stream().map(CompanyDepartmentEmployee::getUserId).distinct().collect(Collectors.toList());
        if (ListUtils.isNotExistsEle(userIdList)) {
            return userVoList;
        }

        String companyDepartmentId = companyDepartmentEmployeeList.get(0).getCompanyDepartmentId();
        String companyId = companyDepartmentEmployeeList.get(0).getCompanyId();
        //获取用户部门
        CompanyDepartment companyDepartment = baseCompanyDepartmentService.getById(companyDepartmentId);
        //获取用户公司
        Company company = baseCompanyService.getById(companyId);

        Map<String, CompanyDepartmentEmployee> userIdMapCompanyDepartmentEmployeeMap = companyDepartmentEmployeeList.stream().collect(Collectors.toMap(CompanyDepartmentEmployee::getUserId, d -> d));

        //获取公司所有角色
        List<PermissionRole> companyPermissionRoleList = basePermissionRoleService.lambdaQuery().eq(PermissionRole::getCompanyId, companyId).list();

        //查询用户信息
        List<User> userList = baseUserService.lambdaQuery()
                .in(User::getUserId, userIdList)
                .list();
        if (ListUtils.isNotExistsEle(userList)) {
            return userVoList;
        }

        //转换简单对象
        userVoList = UserMapstruct.INSTANCE.toUserAndCompanySimpleVoList(userList);
        userVoList.forEach(userVo -> {

            userVo.setCompanyId(company.getCompanyId());
            userVo.setCompanyName(company.getCompanyName());
            userVo.setCompanyLevel(company.getCompanyLevel());
            userVo.setCompanyDepartmentId(companyDepartment.getCompanyDepartmentId());
            userVo.setCompanyDepartmentName(companyDepartment.getCompanyDepartmentName());

            CompanyDepartmentEmployee companyDepartmentEmployee = userIdMapCompanyDepartmentEmployeeMap.get(userVo.getUserId());
            if (companyDepartmentEmployee != null) {
                userVo.setEmployeeId(companyDepartmentEmployee.getCompanyEmployeeId());
                userVo.setJobName(companyDepartmentEmployee.getJobName());
                userVo.setIsCompanyDepartmentPrincipal(companyDepartmentEmployee.getIsPrincipal());
            }

            //填充用户角色
            List<PermissionRoleMapstruct.PermissionRoleIdAndNameVo> processRoleList = new ArrayList<>();
            userVo.setProcessRoleList(processRoleList);
            List<String> roleIdList = basePermissionMapRoleUserService.getRoleIdByUserIdAndCompanyId(userVo.getUserId(), company.getCompanyId());
            if (ListUtils.isExistsEle(companyPermissionRoleList)) {
                List<PermissionRole> userRoleList = companyPermissionRoleList.stream().filter(d -> roleIdList.contains(d.getPermissionRoleId())).collect(Collectors.toList());
                for (PermissionRole permissionRole : userRoleList) {
                    PermissionRoleMapstruct.PermissionRoleIdAndNameVo permissionRoleIdAndNameVo = new PermissionRoleMapstruct.PermissionRoleIdAndNameVo();
                    processRoleList.add(permissionRoleIdAndNameVo);

                    permissionRoleIdAndNameVo.setPermissionRoleId(permissionRole.getPermissionRoleId());
                    permissionRoleIdAndNameVo.setPermissionRoleName(permissionRole.getRoleName());
                }
            }
        });
        return userVoList;
    }

    @Transactional(rollbackFor = Exception.class)
    public void delByCompanyId(String companyId) {
        this.lambdaUpdate().eq(CompanyDepartmentEmployee::getCompanyId,companyId).remove();
    }
}
